﻿using System;

namespace System.Collections.Generic
{
	public class CachedList<T> : CachedPool<T>, ICloneable
	{
		public CachedList() : base((CachedPool<T> p) => default(T))
		{
		}

		public CachedList(int capacity) : base(capacity, (CachedPool<T> p) => default(T))
		{
		}

		public LinkedListNode<T> AddAfter(LinkedListNode<T> node, T value)
		{
			LinkedListNode<T> linkedListNode = AllocAfter(node);
			linkedListNode.Value = value;

			return linkedListNode;
		}

		public LinkedListNode<T> AddBefore(LinkedListNode<T> node, T value)
		{
			LinkedListNode<T> linkedListNode = AllocBefore(node);
			linkedListNode.Value = value;

			return linkedListNode;
		}

		public LinkedListNode<T> AddFirst(T value)
		{
			LinkedListNode<T> linkedListNode = AllocFirst();
			linkedListNode.Value = value;

			return linkedListNode;
		}

		public LinkedListNode<T> AddLast(T value)
		{
			LinkedListNode<T> linkedListNode = AllocLast();
			linkedListNode.Value = value;

			return linkedListNode;
		}

		public object Clone()
		{
			return CachedList<T>.Copy(this);
		}

		public static CachedList<T> Copy(CachedList<T> src)
		{
			CachedList<T> cachedList = new CachedList<T>(src.Capacity);

			for (LinkedListNode<T> linkedListNode = src.First; linkedListNode != null; linkedListNode = linkedListNode.Next)
			{
				cachedList.AddLast(linkedListNode.Value);
			}

			return cachedList;
		}

		public void CopyTo(T[] array, int index)
		{
			if (array.Length < Count)
			{
				throw new ArgumentOutOfRangeException(string.Format("ERROR: CachedPool.CopyTo() failed. out of range(dst len = {0}, end idx = {1})", array.Length, index + Count));
			}

			LinkedListNode<T> linkedListNode = First;
			for (int i = 0; i < Count; i++)
			{
				array[index + i] = linkedListNode.Value;
				linkedListNode = linkedListNode.Next;
			}
		}
	}
}
